package com.vlyman.weixin.send;

import com.alibaba.fastjson.JSONObject;
import com.vlyman.weixin.consts.WxUriConsts;
import com.vlyman.weixin.entity.MessageDataVo;
import com.vlyman.weixin.entity.MessageMiniProgramVo;
import com.vlyman.weixin.entity.MessageSendVo;
import com.vlyman.weixin.utils.HttpUtil;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 类描述：
 *	 微信发送消息工具类
 *  @author chenjs
 *  @date 2019/7/12 16:16
 **/
@Slf4j
public class SendMsg {
	
	/**
	 * 常量描述：<br/>
	 *  模板消息发送url
	 */
	private final static String TEMPLATE_MSG_URL =
			WxUriConsts.WX_TEMPLATE_MSG_SEND.concat("?access_token=");
	private final static String RTN_OK = "ok";

	/**
	 * 方法描述：<br>
	 * 	暂时充当返回信息
	 * 	后续改进
	 * @author chenjs
	 * @param toUserName
	 * @param fromUserName
	 * @param text
	 * @return String
	 * @date 2016年11月9日
	 */
	public static String rtnTextMsg(String toUserName, String fromUserName, String text){
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("xml");
		root.addElement("ToUserName").addCDATA(toUserName);
		root.addElement("FromUserName").addCDATA(fromUserName);
		root.addElement("CreateTime").setText(String.valueOf((System.currentTimeMillis()/1000)));
		root.addElement("MsgType").addCDATA("text");
		root.addElement("Content").addCDATA(text);
		return root.asXML();
	}
	
	/**
	 * 方法描述：<br>
	 * 	单图文信息
	 * @author chenjs
	 * @param toUserName
	 * @param fromUserName
	 * @param title
	 * @param desc
	 * @param imgUrl
	 * @param url
	 * @return String
	 * @date 2017年2月17日
	 */
	public static String singlePicArticle(String toUserName, String fromUserName,
										  String title, String desc, String imgUrl, String url) {
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("xml");
		root.addElement("ToUserName").addCDATA(toUserName);
		root.addElement("FromUserName").addCDATA(fromUserName);
		root.addElement("CreateTime").setText(String.valueOf((System.currentTimeMillis()/1000)));
		root.addElement("MsgType").addCDATA("news");
		root.addElement("ArticleCount").setText("1");
		Element articles = root.addElement("Articles");
		Element item = articles.addElement("item");
		item.addElement("Title").addCDATA(title);
		item.addElement("Description").addCDATA(desc);
		item.addElement("PicUrl").addCDATA(imgUrl);
		item.addElement("Url").addCDATA(url);
		return root.asXML();
	}
	
	public static String picArticles(String toUserName, String fromUserName, List<Article> articleList) {
		if (articleList.isEmpty()) {
			return "";
		}
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("xml");
		root.addElement("ToUserName").addCDATA(toUserName);
		root.addElement("FromUserName").addCDATA(fromUserName);
		root.addElement("CreateTime").setText(String.valueOf((System.currentTimeMillis()/1000)));
		root.addElement("MsgType").addCDATA("news");
		root.addElement("ArticleCount").setText(String.valueOf(articleList.size()));
		Element articles = root.addElement("Articles");
		for (Article article : articleList) {
			Element item = articles.addElement("item");
			item.addElement("Title").addCDATA(article.getTitle());
			item.addElement("Description").addCDATA(article.getDescription());
			item.addElement("PicUrl").addCDATA(article.getPicurl());
			item.addElement("Url").addCDATA(article.getUrl());
		}
		return root.asXML();
	}
	
	/**
	 * 方法描述：<br>
	 * 	发送关键字类型的模板通用方法
	 * @author: chenjs
	 * @param accessToken
	 * @param openid
	 * @param templateId
	 * @param first
	 * @param keywordArr
	 * @param remark
	 * @param url
	 * @return
	 * @date: 2017年1月28日
	 */
	public static boolean sendKeyWordTemplateMessage(String accessToken, String openid, String templateId,
			String first, String[] keywordArr, String remark, String url){
		MessageSendVo msgSend = new MessageSendVo(openid, templateId, url);
		Map<String, MessageDataVo> data = new HashMap<>(8);
		data.put("first", new MessageDataVo(first));
		data.put("remark", new MessageDataVo(remark));
		for (int i = 0; i < keywordArr.length; i++) {
			data.put("keyword"+(i+1), new MessageDataVo(keywordArr[i]));
		}
		msgSend.setData(data);
		return sendTemplateMessage(accessToken, msgSend);
	}
	
	/**
	 * 方法描述：<br>
	 * 	自定义颜色的关键字模板消息通用方法
	 * @author: chenjs
	 * @param accessToken
	 * @param openid
	 * @param templateId
	 * @param firstMD
	 * @param keywordMDList
	 * @param remarkMD
	 * @param url
	 * @return
	 * @date: 2017年8月7日
	 */
	public static boolean sendCustomKeyWordTemplateMessage(String accessToken, String openid, String templateId,
			MessageDataVo firstMD, List<MessageDataVo> keywordMDList, MessageDataVo remarkMD, String url){
		MessageSendVo msgSend = new MessageSendVo(openid, templateId, url);
		Map<String, MessageDataVo> data = new HashMap<>(8);
		data.put("first", firstMD);
		data.put("remark", remarkMD);
		Iterator<MessageDataVo> itr = keywordMDList.iterator();
		int index = 1;
		while (itr.hasNext()) {
			MessageDataVo keywordData = itr.next();
			data.put("keyword"+index, keywordData);
			index++;
		}
		msgSend.setData(data);
		return sendTemplateMessage(accessToken, msgSend);
	}

	/**
	 * 方法描述：
	 *   自定义颜色的关键字模板消息通用方法
	 *   PS. 带小程序跳转
	 *  @author chenjs
	 * 	@param accessToken
	 * 	@param openid
	 * 	@param templateId
	 * 	@param firstMD
	 * 	@param miniprogram
	 * 	@param keywordMDList
	 * 	@param remarkMD
	 * 	@param url
	 *  @return
	 *  @throws Exception 抛出错误
	 *  @date 2021/6/7 11:39
	 */
	public static boolean sendCustomKeyWordWithMiniProgramTemplateMessage(String accessToken, String openid, String templateId,
																		  MessageDataVo firstMD, MessageMiniProgramVo miniprogram,
																		  List<MessageDataVo> keywordMDList, MessageDataVo remarkMD, String url){
		MessageSendVo msgSend = new MessageSendVo(openid, templateId, miniprogram, url);
		Map<String, MessageDataVo> data = new HashMap<>(8);
		data.put("first", firstMD);
		data.put("remark", remarkMD);
		Iterator<MessageDataVo> itr = keywordMDList.iterator();
		int index = 1;
		while (itr.hasNext()) {
			MessageDataVo keywordData = itr.next();
			data.put("keyword"+index, keywordData);
			index++;
		}
		msgSend.setData(data);
		return sendTemplateMessage(accessToken, msgSend);
	}
	
	/**
	 * 方法描述：
	 * 	自定义颜色的非关键字模板消息通用方法
	 * @author: chenjs
	 * @param accessToken
	 * @param openid
	 * @param templateId
	 * @param keys
	 * @param mdlist
	 * @param url
	 * @return
	 * @date: 2017年12月29日
	 */
	public static boolean sendCustomerSpecialTemplateMessage(String accessToken, String openid, String templateId,
			String[] keys, List<MessageDataVo> mdlist, String url) {
		MessageSendVo msgSend = new MessageSendVo(openid, templateId, url);
		Map<String, MessageDataVo> data = new HashMap<>(8);
		for (int i = 0; i < keys.length; i++) {
			String key = keys[i];
			data.put(key, mdlist.get(i));
		}
		msgSend.setData(data);
		return sendTemplateMessage(accessToken, msgSend);
	}

	public static boolean sendTemplateMessage(String accessToken, MessageSendVo msgSend) {
		try {
			String response = HttpUtil.post(TEMPLATE_MSG_URL.concat(accessToken), JSONObject.toJSONString(msgSend));
			JSONObject jObj = JSONObject.parseObject(response);
			String errmsg = jObj.getString("errmsg");
			if (StringUtils.isNotBlank(errmsg) && RTN_OK.equals(errmsg)) {
				return true;
			} else {
				log.error("调用微信发送模板消息接口失败！返回报文："+response);
				return false;
			}
		} catch (Exception e) {
			log.error("调用微信发送模板消息接口失败！", e);
			return false;
		}
	}
	
	/**
	 * 方法描述：<br>
	 * 	图片消息
	 * @author chenjs
	 * @param toUserName
	 * @param mediaId
	 * @return String
	 * @date 2017年3月17日
	 */
	public static String pictureMsg(String toUserName, String fromUserName, String mediaId) {
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("xml");
		root.addElement("ToUserName").addCDATA(toUserName);
		root.addElement("FromUserName").addCDATA(fromUserName);
		root.addElement("CreateTime").setText(String.valueOf((System.currentTimeMillis()/1000)));
		root.addElement("MsgType").addCDATA("image");
		Element image = root.addElement("Image");
		image.addElement("MediaId").addCDATA(mediaId);
		return root.asXML();
	}
}
